#include "libs.h"
#define SCREEN_SIZE 792

#define GCONF_ROOT "/apps/maemo/heart_monitor"
#define GCONF_KEY_NAME "/apps/maemo/heart_monitor/NAME"
#define GCONF_KEY_MAC "/apps/maemo/heart_monitor/MAC"

gint FONT_SIZE = 30;
gint KA = 20;
gint TIMEOUT = 3000;

gint K = 5;
gint SPEED = 1;
gint tmpK;
gint tmpSpeed;
gint SizeX = 0;
gboolean FILTER = 0;
gdouble bpm = 0;
gdouble max = 30;
gboolean flag = 0;
gboolean searchFinish = TRUE;
gint countOut = 0;

G_LOCK_DEFINE(1);

gchar message[100] = { 0 };

typedef struct 
{
	gchar NAME[248];
	gchar MAC[19];	
} Devices;

Devices list[100];
Devices dev_default;
	
enum
{
	DEV_ID = 0,
	DEV_MAC,
	COLUMNS	
};

static void destroy ();
static void show_info_banner (GtkWidget *parent, gchar* info);
static void create_options ();
static void drawEcg (GtkWidget*, GdkEventExpose*);
static void drawAccel (GtkWidget*, GdkEventExpose*);
static void changeMode (GtkNotebook*, GtkNotebookPage*, gint);
static void search_bt_device (GtkWidget *treeview);
static void start_btn_clicked ();
static void stop_btn_clicked ();
static void filter_btn_clicked (GtkToggleToolButton *button);
static gpointer find_device ();
static GtkWidget* setup_tree_view (GtkWidget *scrollBar);
static gpointer start ();
static void parse (guchar* buf, gint size);
static gboolean time_handler (GtkWidget*);
static void zoomChanged ();
static void speedChanged ();
	
GtkWidget *window;  
GtkWidget *drawingEcg, *drawingAccel;
GtkWidget *options;
GtkWidget *radio5, *radio10, *radio20;
GtkWidget *radioSp125, *radioSp25, *radioSp50;

GtkWidget* treeview;	
GtkListStore *store;
GtkTreeIter iter;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GtkWidget *scrollBar;
GtkWidget *optionsNotebook;

gint mode = 0; // 0 - ECG, 1 - Accel
gboolean start_btn_is_pressed = FALSE;

gdouble batteryLevel = 0.0;
gboolean isOptions = FALSE;
gint EcgDataFormat = 0;
gint AccDataFormat = 0;
gint EcgLength = 0;
gint AccLength = 0;
gint posLastEnd = 5;

gint nk = 10;
gint count = 0;

gdouble EcgData [4000];
gdouble AccData [4000];
gdouble HLP[4000];
gboolean masRR[4000];
gint RR[500];
gint Rbgn = 0;
gint Rend = 0;

gint posEcg = 0;
gint posAcc = 0;

gint main ( gint argc, gchar **argv )	{
    GtkWidget *notebook;
    GtkWidget *labelEcg, *labelAccel;
    GtkWidget *menuOptions;
    HildonAppMenu *menuBar;
    GtkToolItem *startBtn, *stopBtn, *filterBtn;
 	GtkWidget *toolbar;
	gchar *name, *mac;
	gchar tmp[100];

	HildonProgram *program;
    hildon_gtk_init (&argc, &argv);
    
    if(!g_thread_supported ())
    	g_thread_init (NULL);
    
    window = hildon_window_new ();
	program = hildon_program_get_instance ();
	hildon_program_add_window (program, HILDON_WINDOW (window));


	GConfClient* client;
	client = gconf_client_get_default();
	gconf_client_add_dir (client, GCONF_ROOT, GCONF_CLIENT_PRELOAD_NONE, NULL);
	name = gconf_client_get_string(client, GCONF_KEY_NAME, NULL);
	mac = gconf_client_get_string(client, GCONF_KEY_MAC, NULL);
	
	if( (name != NULL) && (mac != NULL) )	{
		g_debug("name = %s, mac = %s\n", name, mac);
		
		strcpy (dev_default.NAME, name);
		strcpy (dev_default.MAC, mac);
		sprintf (tmp, "Heart Monitor - %s", dev_default.NAME);
		g_set_application_name (tmp);
	}
	else	{
		g_debug("name || mac == NULL!\n");
	
		g_set_application_name ("Heart Monitor");
	}

    gtk_container_set_border_width (GTK_CONTAINER (window), 2);
    
    g_timeout_add (300, (GSourceFunc) time_handler, (gpointer) window);
    
    menuOptions = hildon_button_new_with_text (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Options", NULL);
    
    g_signal_connect (menuOptions,	"clicked", G_CALLBACK(create_options), NULL);
    
    menuBar =  HILDON_APP_MENU (hildon_app_menu_new ());
	hildon_app_menu_append (menuBar, GTK_BUTTON (menuOptions));
  	gtk_widget_show_all (GTK_WIDGET (menuBar));

	hildon_window_set_app_menu (HILDON_WINDOW (window), menuBar);
  
    labelEcg = gtk_label_new ("ECG");
    labelAccel = gtk_label_new ("Accel");

    drawingEcg = gtk_drawing_area_new ();
    drawingAccel = gtk_drawing_area_new ();
        
    notebook = gtk_notebook_new ();
    gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), drawingEcg, labelEcg);
    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), drawingAccel, labelAccel);
    gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);        
 
	toolbar = gtk_toolbar_new ();
	startBtn = gtk_tool_button_new_from_stock (GTK_STOCK_MEDIA_PLAY);
	stopBtn = gtk_tool_button_new_from_stock (GTK_STOCK_MEDIA_STOP); 

	filterBtn = gtk_toggle_tool_button_new ();
	gtk_tool_button_set_label ( GTK_TOOL_BUTTON(filterBtn), "filter"); 

	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), startBtn, 0);
	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), stopBtn, 1);
	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), filterBtn, 2);

	hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR(toolbar));
 
    gtk_container_add (GTK_CONTAINER (window), notebook);
	
	g_signal_connect (G_OBJECT(window), 		"destroy", 		G_CALLBACK(destroy), 	NULL);
	g_signal_connect (G_OBJECT(notebook),		"switch_page", 	G_CALLBACK(changeMode), NULL);
    g_signal_connect (G_OBJECT(drawingEcg),		"expose_event", G_CALLBACK(drawEcg), 	NULL);
    g_signal_connect (G_OBJECT(drawingAccel),	"expose_event", G_CALLBACK(drawAccel),	NULL);
    g_signal_connect (G_OBJECT(startBtn),		"clicked", 		G_CALLBACK (start_btn_clicked),	NULL); 
    g_signal_connect (G_OBJECT(stopBtn),		"clicked", 		G_CALLBACK (stop_btn_clicked),	NULL); 
 	g_signal_connect (G_OBJECT(filterBtn),		"toggled", 		G_CALLBACK (filter_btn_clicked),	NULL); 
    
    tmpK=K;
    tmpSpeed = SPEED;

    gtk_widget_show_all (window);
    gtk_main ();

    g_object_unref (G_OBJECT (client));
	if(name)	g_free(name);
	if(mac)		g_free(mac);	
    return FALSE;
}


static void destroy ()	{
	g_debug( "Exit\n" );
	gtk_main_quit ();
}

static void search_bt_device (GtkWidget *treeview)	{
	g_debug ( "Search BT Device...\n" );

	gtk_list_store_clear ( store );
	
	GError *error = NULL;	
	GThread *thread_id = g_thread_create ( find_device, NULL, TRUE, &error );
	if( error )	{
		g_debug ( "Can't create thread : search_bt_device\n" );
	}
}

static gboolean time_handler (GtkWidget* widget)	{
	if ( widget->window == NULL )	{ 
  		return FALSE;
	}
  	
//	if (!start_btn_is_pressed)
//		return FALSE;
	if( strcmp(message, "") != 0 )	{
		show_info_banner (window, message);
		memset(message, 0, sizeof(message));
	}
	gtk_widget_queue_draw (widget);
	return TRUE;
}

static void drawEcg (GtkWidget* drawarea, GdkEventExpose* event)	{
//	g_debug ("ECG\n");
	cairo_t *cr = gdk_cairo_create (drawarea->window);
	cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
	cairo_set_source_rgb (cr, 0, 0, 0);
	cairo_fill (cr);
	cairo_stroke (cr);
		
	gchar bufBattery[10];
	gchar bufBpm[10];

	if (SPEED != 1)	{
		bpm = 0;
	}
	
	G_LOCK(1);

	if ( batteryLevel > 66 )	{
		cairo_set_source_rgb (cr, 0, 1, 0);
	}
	else if ( batteryLevel > 33 )	{
		cairo_set_source_rgb (cr, 1, 1, 0);
	}
	else	{
		cairo_set_source_rgb (cr, 1, 0, 0);
	}
	
	sprintf(bufBattery, "%1.0f %%", batteryLevel);
	sprintf(bufBpm, "%1.0f bpm", bpm);

	G_UNLOCK(1);

//	sprintf(buf, "%1.0f %%", batteryLevel);
	cairo_set_font_size(cr, FONT_SIZE);
	cairo_move_to (cr, event->area.x + 20, event->area.y + FONT_SIZE);
	cairo_show_text(cr, bufBattery);
	cairo_stroke (cr);

	cairo_set_source_rgb (cr,1, 1, 1);	
	cairo_move_to (cr, event->area.width - 120, event->area.y + FONT_SIZE);
	cairo_show_text(cr, bufBpm);
	cairo_stroke(cr);

	cairo_move_to (cr, event->area.x, (event->area.height/3)*2);
	gint i, j;
	for(i=0, j=0; i < SizeX; i++, j++)	{
		if((EcgData[i] == 100000 || EcgData[i] == -100000) || (i!= 0 && (EcgData[i-1] == 100000 || EcgData[i-1] == -100000)))
			cairo_move_to (cr, event->area.x+j, (event->area.height/3)*2 + EcgData[(i + 1)%SizeX]*K);//cairo_stroke (cr);
		else	{
			if ( masRR[i] )	{
				cairo_move_to (cr, event->area.x+j, event->area.height);
				cairo_line_to (cr, event->area.x+j, event->area.height - 15);
				cairo_stroke (cr);
				cairo_move_to (cr, event->area.x+((j-1+SizeX)%SizeX), (event->area.height/3)*2 + EcgData[(i-1+SizeX)%SizeX]*K);
			}
			cairo_line_to (cr, event->area.x+j, (event->area.height/3)*2 + EcgData[i]*K);
		}
		if( i % 20 == 0)	{
			cairo_stroke(cr);
			cairo_move_to (cr, event->area.x+j, (event->area.height/3)*2 + EcgData[i]*K);	
		}	
	}
	cairo_stroke (cr);
	gtk_widget_show_all (drawarea);

	SizeX = event->area.width;
}

static void drawAccel(GtkWidget* drawarea, GdkEventExpose* event)	{
//	g_debug ("Accel\n");
	cairo_t *cr = gdk_cairo_create (drawarea->window);
	cairo_rectangle (cr, event->area.x + FONT_SIZE, event->area.y, event->area.width - FONT_SIZE, event->area.height);
	cairo_set_line_width (cr, 1);
	cairo_set_source_rgb (cr, 0, 0, 0);
	cairo_fill (cr);
	
	cairo_set_font_size (cr, FONT_SIZE);
	cairo_set_source_rgb (cr, 1, 1, 1);
	cairo_move_to (cr, FONT_SIZE/5, (event->area.height/6) + FONT_SIZE/2);
	cairo_show_text(cr, "X");
	cairo_move_to (cr, FONT_SIZE/5, (event->area.height/6)*3 + FONT_SIZE/2);
	cairo_show_text(cr, "Y");
	cairo_move_to (cr, FONT_SIZE/5, (event->area.height/6)*5 + FONT_SIZE/2);
	cairo_show_text(cr, "Z");
	cairo_stroke (cr);
	
	cairo_set_line_width (cr, 2);
	gint i = 0, j = 0;
	cairo_move_to (cr, FONT_SIZE, (event->area.height/6)*1  + FONT_SIZE/10);
	for(i=0, j=0; i < (SizeX*3); i+=3, j++)	{
		if((AccData[i] == 100000 || AccData[i] == -100000) || (i >= 3 && (AccData[i-3] == 100000 || AccData[i-3] == -100000)))
			cairo_move_to (cr, FONT_SIZE+j, (event->area.height/6)*1 + FONT_SIZE/10 - AccData[(i+3)%(SizeX*3)]*KA);//cairo_stroke (cr);
		else
			cairo_line_to (cr, FONT_SIZE+j, (event->area.height/6)*1 + FONT_SIZE/10 - AccData[i]*KA);
//		if( i % 120 == 0)	{
//			cairo_stroke(cr);
//			cairo_move_to (cr, FONT_SIZE+j, (event->area.height/6)*1 + FONT_SIZE/10 - AccData[i]*KA);	
//		}	
	}

	cairo_move_to (cr, FONT_SIZE, (event->area.height/6)*3  + FONT_SIZE/10);
	for(i=1, j=0; i < (SizeX*3); i+=3, j++)	{
		if((AccData[i] == 100000 || AccData[i] == -100000) || (i >= 3 && (AccData[i-3] == 100000 || AccData[i-3] == -100000)))
			cairo_move_to (cr, FONT_SIZE+j, (event->area.height/6)*3 + FONT_SIZE/10 - AccData[(i+3)%(SizeX*3)]*KA);//cairo_stroke (cr);
		else	
			cairo_line_to (cr, FONT_SIZE+j, (event->area.height/6)*3 + FONT_SIZE/10 - AccData[i]*KA);
//		if( i % 120 == 0)	{
//			cairo_stroke(cr);
//			cairo_move_to (cr, FONT_SIZE+j, (event->area.height/6)*3 + FONT_SIZE/10 - AccData[i]*KA);	
//		}	
		
	}
	cairo_move_to (cr, FONT_SIZE, (event->area.height/6)*5  + FONT_SIZE/10);
	for(i=2, j=0; i < (SizeX*3); i+=3, j++)	{
		if((AccData[i] == 100000 || AccData[i] == -100000) || ( i >= 3 && (AccData[i-3] == 100000 || AccData[i-3] == -100000)))
			cairo_move_to (cr, FONT_SIZE+j, (event->area.height/6)*5 + FONT_SIZE/10 - AccData[(i+3)%(SizeX*3)]*KA);//cairo_stroke (cr);
		else
			cairo_line_to (cr, FONT_SIZE+j, (event->area.height/6)*5 + FONT_SIZE/10 - AccData[i]*KA);
//		if( i % 120 == 0)	{
//			cairo_stroke(cr);
//			cairo_move_to (cr, FONT_SIZE+j, (event->area.height/6)*5 + FONT_SIZE/10 - AccData[i]*KA);	
//		}	
	}
	cairo_stroke (cr);
	gtk_widget_show_all (drawarea);
	
	SizeX = event->area.width;
}

static void changeMode (GtkNotebook* notebook, GtkNotebookPage* page, gint page_num)	{
	mode = page_num;
	g_debug ("%d\n", page_num);
}

static void create_options ()	{
	GtkWidget *vbox;
	GtkWidget *labelConnection, *labelSettings, *labelSpeed, *labelK;
	GtkWidget *connectionVbox;
	GtkWidget *settingsVbox;
	GtkWidget *kHbox, *sHbox;
	GtkWidget *searchBtn;
	GtkWidget *separator;

	isOptions = TRUE;
	
	options = gtk_dialog_new_with_buttons ("Options", NULL, 
											GTK_DIALOG_MODAL, 
											GTK_STOCK_OK, GTK_RESPONSE_OK,
											GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
											NULL);
	gtk_dialog_set_default_response (GTK_DIALOG (options), GTK_RESPONSE_OK);
	
	labelConnection = gtk_label_new ("Connection");
	labelSettings = gtk_label_new ("Settings");
	labelSpeed = gtk_label_new ("Horizontal Scale, mm/s");
	labelK = gtk_label_new ("Vertical Scale, mm/mV");
	
	scrollBar = gtk_scrolled_window_new (NULL, NULL);
	scrollBar = setup_tree_view (scrollBar);
	
	searchBtn = hildon_button_new_with_text (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL, "Search", NULL);
	
	connectionVbox = gtk_vbox_new (FALSE,0);
	gtk_box_pack_start (GTK_BOX (connectionVbox), scrollBar, TRUE, TRUE, 0);     
	gtk_box_pack_start (GTK_BOX (connectionVbox), searchBtn, FALSE, TRUE, 0); 
	
	settingsVbox = gtk_vbox_new (FALSE,0);
	radio5  = gtk_radio_button_new_with_label (NULL, "  5");
	radio10 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio5), "10");
	radio20 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio5), "20");
	
	radioSp125 = gtk_radio_button_new_with_label (NULL, "12.5");
	radioSp25  = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radioSp125), "25");
	radioSp50  = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radioSp125), "50");
	
	switch (K)	{
		case 5:	 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio5),  TRUE );
			break;
		case 10: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio10), TRUE );
			break;
		case 20: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio20), TRUE );
	}
	
	switch (SPEED)	{
		case 1: gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radioSp125),  TRUE );
			break;	
		case 2:   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radioSp25), TRUE );
			break;
		case 4:   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radioSp50), TRUE );
			break;
	}
	
	kHbox = gtk_hbox_new (FALSE,0);
	gtk_box_pack_start (GTK_BOX (settingsVbox), labelK, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (kHbox), radio5,  TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (kHbox), radio10, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (kHbox), radio20, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (settingsVbox), kHbox, FALSE, TRUE, 0);
	
	separator = gtk_hseparator_new ();
	sHbox = gtk_hbox_new(FALSE,0);
    gtk_box_pack_start (GTK_BOX (settingsVbox), separator, FALSE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX (settingsVbox), labelSpeed, TRUE, TRUE, 0);    
    gtk_box_pack_start (GTK_BOX (sHbox), radioSp125, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (sHbox), radioSp25, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (sHbox), radioSp50, TRUE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX (settingsVbox), sHbox, TRUE, TRUE, 0); 
	
	optionsNotebook = gtk_notebook_new ();
    gtk_notebook_set_tab_pos (GTK_NOTEBOOK (optionsNotebook), GTK_POS_TOP);
    gtk_notebook_append_page (GTK_NOTEBOOK (optionsNotebook), connectionVbox, labelConnection);
    gtk_notebook_append_page (GTK_NOTEBOOK (optionsNotebook), settingsVbox, labelSettings);
    gtk_notebook_set_current_page (GTK_NOTEBOOK (optionsNotebook), 0);     
    
    g_signal_connect (G_OBJECT(searchBtn),  "clicked", G_CALLBACK (search_bt_device),  options); 
    g_signal_connect (G_OBJECT(radio5),     "toggled", G_CALLBACK(zoomChanged),  NULL);
    g_signal_connect (G_OBJECT(radio10),    "toggled", G_CALLBACK(zoomChanged),  NULL);
    g_signal_connect (G_OBJECT(radio20),    "toggled", G_CALLBACK(zoomChanged),  NULL);   
    g_signal_connect (G_OBJECT(radioSp125), "toggled", G_CALLBACK(speedChanged), NULL);
    g_signal_connect (G_OBJECT(radioSp25),  "toggled", G_CALLBACK(speedChanged), NULL);
    g_signal_connect (G_OBJECT(radioSp50),  "toggled", G_CALLBACK(speedChanged), NULL);        

	vbox=gtk_vbox_new(FALSE,0);
    gtk_box_pack_start (GTK_BOX(vbox), optionsNotebook, FALSE, FALSE, 2);     
    gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG(options)->vbox), vbox);
	
	gtk_widget_show_all (options);
	
	gint result = gtk_dialog_run (GTK_DIALOG(options));
	if(result == GTK_RESPONSE_OK)	{
		g_debug ("response == OK\n");
		
		switch(gtk_notebook_get_current_page (GTK_NOTEBOOK (optionsNotebook)))	{
		case 0:	{
				GtkTreeSelection *selection;
				gchar *name, *addr;
				GtkTreeModel *mod;
				GtkTreeIter it;
				gchar tmp[1024];
				selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
				if (gtk_tree_selection_get_selected (selection, &mod, &it))	{
					gtk_tree_model_get (GTK_TREE_MODEL(store), &it, DEV_ID, &name, DEV_MAC, &addr,-1);	
					strcpy (dev_default.NAME, name);
					strcpy (dev_default.MAC, addr);
					g_debug ("%s - %s\n", dev_default.NAME, dev_default.MAC);
					sprintf (tmp, "Heart Monitor - %s", dev_default.NAME);
					gtk_window_set_title (GTK_WINDOW(window), tmp);
					g_free (name);
					g_free (addr);
    				if ( store )
    					g_object_unref (store);
				}
				else	if( strcmp (dev_default.NAME, "") == 0 ) {
					g_debug ("Nothing selected!\n");	
					strcpy(message, "Nothing selected!");
				}
				break;
			}
		case 1:	{
			K = tmpK;
			SPEED = tmpSpeed;
			g_debug ("K = %d\tSPEED = %d\n", K, SPEED);
			break;
			}
		}
	}
	isOptions = FALSE;
	
	gtk_widget_destroy (options);
}

GtkWidget* setup_tree_view(GtkWidget *scrollBar)	{
//	GtkTreeViewColumn *column;
//	GtkCellRenderer *renderer;

	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollBar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	treeview = gtk_tree_view_new();
	renderer = gtk_cell_renderer_text_new ();
	column = gtk_tree_view_column_new_with_attributes("Select a Bluetooth Device:", renderer, "text", DEV_ID, NULL);
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
	
	store = gtk_list_store_new (COLUMNS, G_TYPE_STRING, G_TYPE_STRING); 
	
	gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
	gtk_widget_show(treeview);
//	GtkTreeSelection* select = gtk_tree_view_get_selection (GTK_TREE_VIEW(treeview));
	gtk_container_add(GTK_CONTAINER(scrollBar), treeview);
	return scrollBar;
}

static gpointer find_device()	{
	searchFinish = FALSE;
	hildon_gtk_window_set_progress_indicator(GTK_WINDOW(options), 1);

    inquiry_info *ii = NULL;
    gint max_rsp, num_rsp;
    gint dev_id, sock, len, flags;
    gint i;
    gchar addr[19] = { 0 };
    gchar name[248] = { 0 };

    dev_id = hci_get_route (NULL);
    sock = hci_open_dev( dev_id );
    if (dev_id < 0 || sock < 0) {
        perror ("opening socket");
        g_thread_exit (GINT_TO_POINTER(0));
    }

    len = 8;
    max_rsp = 255;
    flags = IREQ_CACHE_FLUSH;
    ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
    
    num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
    if ( num_rsp < 0 )	{ 
    	perror ("hci_inquiry");
	}

    for (i=0; (i < num_rsp) && (isOptions); i++) {
        ba2str (&(ii+i)->bdaddr, addr);
        memset (name, 0, 248*sizeof(gchar));
        if (hci_read_remote_name (sock, &(ii+i)->bdaddr, sizeof(name), name, 0) < 0)
        	strcpy (name, "[unknown]");
        g_debug ("%s  %s\n", addr, name);
        strcpy (list[i].NAME, name);
        strcpy (list[i].MAC, addr);
        
        gtk_list_store_append (store, &iter);
        gtk_list_store_set (store, &iter, DEV_ID, name, DEV_MAC, addr, -1);
	}
	
	hildon_gtk_window_set_progress_indicator ( GTK_WINDOW(options), 0 );

	if(name == NULL)	{
		g_debug ("Device not found!\n");	
	}
	else	{
		g_debug ("Search complete succesfully!\n");
	}

    free(ii);
    close (sock);
	searchFinish = TRUE;
    g_thread_exit (GINT_TO_POINTER(0));
	return NULL;
}

static gpointer start()	{

	while(!searchFinish)	{
		sleep(1);
	}

	G_LOCK(1);
	
	memset( EcgData, 0, 4000*sizeof(gdouble));
	memset( AccData, 0, 4000*sizeof(gdouble));
	memset( HLP, 0, 4000*sizeof(gdouble));
	posEcg = 0;
	posAcc = 0;
	bpm = 0;
	batteryLevel = 0;
	countOut = 0;
	memset(masRR, 0, 4000*sizeof(gboolean));

	G_UNLOCK(1);

	posLastEnd = 5;
	flag = 0;
	count = 0;

	strcpy(message, "Connecting...");

	struct sockaddr_rc addr = { 0 };
    gint s, status;
	guchar buf[1024] = { 0 };
    gint bytes_read=0, i=0;

    s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

    addr.rc_family = AF_BLUETOOTH;
    addr.rc_channel = (uint8_t) 1;
    str2ba( dev_default.MAC, &addr.rc_bdaddr );

    status = connect (s, (struct sockaddr *)&addr, sizeof(addr));

    if( status < 0 )	{
		perror ("Error: connection failed!\n");
		strcpy(message, "Error: connection failed!");
		return NULL;
    }
	else	{
		strcpy(message, "Connection set");;
	}
	
    while(start_btn_is_pressed)	{
	    bytes_read = read(s, buf, sizeof(buf));
	    if( bytes_read > 0 ) {
			g_debug ("%d\n", bytes_read);
			for(i=0; i<bytes_read; i++)	{
			    g_debug (" %x ", buf[i]);
			}
			g_debug ("\n");
			parse(buf, bytes_read);
	    }
    }

    close (s);
    g_thread_exit(GINT_TO_POINTER(0));
	return NULL;
}

static void start_btn_clicked()	{
	g_debug ("Start btn clicked\n");
	
	start_btn_is_pressed = TRUE;
	
	if(strcmp(dev_default.MAC, "") == 0)
		create_options();
	else	{
		GConfClient* client;
		client = gconf_client_get_default();
		gconf_client_add_dir (client, GCONF_ROOT, GCONF_CLIENT_PRELOAD_NONE, NULL);
		gconf_client_set_string(client, GCONF_KEY_NAME, dev_default.NAME, NULL );
		gconf_client_set_string(client, GCONF_KEY_MAC, dev_default.MAC, NULL );

		GError *error = NULL;
		GThread *thread_id = g_thread_create (start, NULL, TRUE, &error);
	}
}

static void stop_btn_clicked()	{
	g_debug ("Stop btn clicked\n");	
	strcpy(message, "Transmission stopped");
	start_btn_is_pressed = FALSE;
}

static void filter_btn_clicked(GtkToggleToolButton *button)	{
	FILTER = gtk_toggle_tool_button_get_active(button);
	g_debug ("FILTER = %d\n", FILTER);
}

static void parse(guchar* buf, gint size)	{
	g_debug ("Parse started\n");
	
	if( !((buf[0] == 0) && ((guchar)buf[1] == 254)) )	{
		g_debug ("Packet header error! Sync Bytes\n");
		return;
	}
	
	G_LOCK(1);	
	batteryLevel = (gdouble)((guchar)buf[2])/2;
	G_UNLOCK(1);
	
	g_debug("%f\n", batteryLevel); 	
	
	if((guchar)buf[6] != 170)	{
		g_debug ("ECG header error! - %d\n", buf[6]);
		return;
	}
	
	EcgLength = buf[7]*256 + buf[8];	
	EcgDataFormat = buf[9];

//	g_debug ("EcgLength - %d, EcgDataFormat - %d\n", EcgLength, EcgDataFormat);
	gint i=0, j=0, k=0, tmpEcg=0;
	for(i=0, j=posEcg; j < posEcg+EcgLength - 5; i+=SPEED, j++)	{
		EcgData[(j % SizeX)] = (gdouble)((2*2.66*buf[11+i])/255 - 2.66)*15;
	}
	memset(masRR + (posEcg%SizeX), 0, (j-(posEcg%SizeX))*sizeof(gboolean));

	if(	FILTER )	{
		if( SPEED != 1	)	{
			strcpy(message, "Horizontal scale set to 12.5 mm/s");
			SPEED = 1;
			return;
		} // от -7 до +8
		for(i=0, j=posEcg - 8; i <= EcgLength - 5 + 7; i+=SPEED, j+=1)	{
			tmpEcg = 0;
			for(k=-7; k<=8; k++)	{
				if( j + k < 0 )	{
					j+=SizeX;	
				}
				tmpEcg += (668 - 20*k*k)*EcgData[((j+k) % SizeX)]; 
			}
			EcgData[(j % SizeX)] = ((gdouble)1/4420)*tmpEcg;
		}
	}

	gint t=0, s=0;

	gint posEcgC = (gint)(posEcg + (1*((gdouble)EcgLength - 5)/SPEED ));
		
	if (FILTER)
		posEcgC -= 8;

	if(posEcgC <= posLastEnd)
		posEcgC+= SizeX;
	
	memset(HLP, 0, 4000*sizeof(gdouble));
	for( t = 0; t < SizeX; t++ )	{
		for( s = t - nk/2; s <= t + nk/2; s++ )	{
			if(s < 0)	{
				HLP[(t%SizeX)] += pow((( 2*EcgData[((s + SizeX)%SizeX)]) - 2*EcgData[((s + 1 + SizeX) % SizeX)] - EcgData[((s + 2 + SizeX) % SizeX)]) , 2);	
			}
			else
				HLP[(t%SizeX)] += pow((( 2*EcgData[(s % SizeX)]) - 2*EcgData[((s + 1) % SizeX)] - EcgData[((s + 2) % SizeX)]) , 2);	
		}
		HLP[(t%SizeX)] /= nk;
	}

	max = 10;
	for(t = 0; t < SizeX; t++)	{
		if(HLP[(t%SizeX)] > max)
			max = HLP[(t%SizeX)];
	}
/*	
	for(t= posLastEnd + nk/2; t < posEcgC - nk/2; t++)	{
		if(HLP[(t%SizeX)] > max)
			max = HLP[(t%SizeX)];
	}
*/	
	gint xbeg=0, xend=0;
//	printf("posLastEnd = %d, posEcgC = %d\n", posLastEnd, posEcgC);
//	printf("0.4*max = %1.1f", 0.4*max);
	for(t = posLastEnd; t <= (posEcgC/* - nk/2*/) && (xbeg == xend); t++ )	{
		if(HLP[(t%SizeX)] > (0.4*max))	{
			xbeg = t;
			while( (t <= (posEcgC/* - nk/2*/)) && (HLP[(t%SizeX)] > (0.4*max)) )
				t++;
			if(t > posEcgC)	{
				printf("\t\txbeg = %d\txend = %d", xbeg, t);
				xbeg = 0;
				xend = 0;
			}
			else
				xend=t;
			continue;
		}
	}
//	printf("xbeg = %d, xend = %d, SizeX = %d\n", xbeg%SizeX, xend%SizeX, SizeX);
	
	gint localMax=0;
	gdouble lm=0;
	if(xbeg != xend && RR[count-1] == 0/*  && abs((xend%SizeX) - (posLastEnd%SizeX)) > 70*/)	{
		lm=HLP[(xbeg%SizeX)];
		localMax = xbeg;
		for(t = xbeg; t <= xend; t++)	{
			if(HLP[(t%SizeX)] > lm)	{
				lm = HLP[(t%SizeX)];
				localMax = t;
			}
		}
	}
	if(xend != 0)
		posLastEnd = (xend%SizeX);
	
	gint a=0;
	RR[count]=localMax;

	Rend = localMax;

	if(xend == xbeg || /*count == 1*/RR[count-1] != 0 || xend <= (xbeg + 3)) {
		RR[count] = 0;	
		countOut +=1;
		Rend = 0;
	}
	else	{
		countOut = 0;
// не нужно
		gint m = count - 1;
		while( (RR[m] == 0) && (m > 0) )	{
			m-=1;
		} 
//
		a = ((RR[count]%SizeX) - (RR[m]%SizeX)); 
//		a = Rend - Rbgn;

		if( a < 0)
			a+=SizeX;
//		printf("a = %d\n", a);
		
		gdouble tmpBpm = (gdouble)(300*60)/a;
//		printf("tmpBpm = %1.0f\n", tmpBpm);

		if( flag/* && ( (tmpBpm > bpm*0.8 && tmpBpm < bpm*1.2) || (bpm == 0))*/ )	{
			G_LOCK(1);
			bpm = tmpBpm;
			masRR[(localMax % SizeX)] = 1;
			G_UNLOCK(1);
			countOut = 0; 
//			count = 0;
//			Rbgn = localMax;
//			Rend = 0;
		}
		else	{
			countOut+=1;
		}


			
		if(count > 10)	{
			count = 0;
			memset(RR, 0, 500*sizeof(gint));
			RR[0] = localMax;
			flag = 1;
		}	
	}
	count++;

	if( countOut > 10 )	{
		G_LOCK(1);
		bpm = 0;
		G_UNLOCK(1);
		max = 30;
	}

	posEcg = (gint)(( posEcg + ((gdouble)EcgLength - 5)/SPEED ))%SizeX;
	
	for(i=j+40; j<i; j+=2)	{
		EcgData[j] = 100000;
		EcgData[j+1] -= 100000;
	}
/*
	g_debug("MAS_ECG: ");
	for(j=0; j<posEcg; j++)
		g_debug ("%1.1f ", EcgData[j]);
	g_debug ("\n");
*/


	if( (buf[6 + EcgLength] != 85) && (buf[6 + EcgLength] != 86))	{
		g_debug ("Acc header error! - %d\n", buf[6 + EcgLength]);
	}
	
	AccLength = buf[7 + EcgLength]*256 + buf[8 + EcgLength];	
	AccDataFormat = buf[6 + EcgLength];

//	g_debug ("AccLength - %d, AccDataFormat - %d\n", AccLength, AccDataFormat);

	if(buf[6 + EcgLength] == 85)	{  // 2 axes
		for(i=0, j=posAcc; j<posAcc+AccLength-5; j++, i++)	{
			AccData[j % (SizeX*2)] = (2*2*(guchar)buf[11+EcgLength+i])/255 - 2;	
		}
		for(j=posAcc+AccLength-5; j<=posAcc+AccLength-5+90; j+=4)	{
			AccData[j % (SizeX*2)] = 100000;
			AccData[(j+1) % (SizeX*2)] = 100000;
			AccData[(j+2) % (SizeX*2)] -= 100000;
			AccData[(j+3) % (SizeX*2)] -= 100000;
		}
		posAcc = (posAcc + AccLength-5) % (SizeX*2);
	}
	else if(buf[6 + EcgLength] == 86)	{  // 3 axes
		for(i=0, j=posAcc; j<posAcc+AccLength-5; j++, i++)	{
			AccData[j % (SizeX*3)] = (((gdouble)2*2.7*(guchar)(buf[11+EcgLength+i])))/255 - 2.7;	
		}
		for(j=posAcc+AccLength-5; j<=posAcc+AccLength-5+90; j+=6)	{
			AccData[j % (SizeX*3)] = 100000;
			AccData[(j+1) % (SizeX*3)] = 100000;
			AccData[(j+2) % (SizeX*3)] = 100000;
			AccData[(j+3) % (SizeX*3)] -= 100000;
			AccData[(j+4) % (SizeX*3)] -= 100000;
			AccData[(j+5) % (SizeX*3)] -= 100000;
		}
		posAcc = (posAcc + AccLength-5) % (SizeX*3);
	}
/*		
	for ( j = 0; j < posAcc; j++ )	{
		g_debug("%1.1f ", AccData[j]);
	}
	g_debug("\n");
*/
}

static void show_info_banner (GtkWidget *parent, gchar* info)	{
	GtkWidget *banner;
	banner = hildon_banner_show_information (parent, NULL, info);
	hildon_banner_set_timeout (HILDON_BANNER (banner), TIMEOUT);
	return;
}

static void zoomChanged ()	{
	if (GTK_TOGGLE_BUTTON (radio5)->active) 
		tmpK = 5;
	else if (GTK_TOGGLE_BUTTON (radio10)->active)
    	tmpK = 10;
	else if (GTK_TOGGLE_BUTTON (radio20)->active)
		tmpK = 20;
	g_print("tmpK = %d\n", tmpK);
}

static void speedChanged ()	{
	if (GTK_TOGGLE_BUTTON (radioSp125)->active) 
		tmpSpeed = 1;
	else if (GTK_TOGGLE_BUTTON (radioSp25)->active)
    	tmpSpeed = 2;
	else if (GTK_TOGGLE_BUTTON (radioSp50)->active)
		tmpSpeed = 4;
	g_print("tmpSpeed = %d\n", tmpSpeed);
}
